package org.jeecg.tender.taskJob.cg11185;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.jeecg.attachment.service.ISysAttachmentService;
import org.jeecg.common.MessageSNUtil;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.FileUtil;
import org.jeecg.tender.config.WebDriverConfig;
import org.jeecg.tender.information.entity.TenderInformation;
import org.jeecg.tender.information.service.ITenderInformationService;
import org.jeecg.tender.keyword.service.ITenderSecurityKeywordManagementService;
import org.jeecg.tender.project.dto.req.SendProjectNoticeReqDto;
import org.jeecg.tender.project.service.ITenderProjectNoticeService;
import org.jeecg.tender.taskJob.cg11185.support.BuildTenderInfo;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.WindowType;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.File;
import java.time.Duration;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 邮政采购爬取任务
 * @author: qiang.zhou
 * @date: 2025/2/28 10:41
 **/
@Slf4j
@Component
public class Cg11185TaskJob implements Job {

    static final String JOB_NAME = "cg11185";

    @Resource
    private WebDriverConfig webDriverConfig;
    @Resource
    private ITenderInformationService tenderInformationService;
    @Resource
    private ITenderSecurityKeywordManagementService tenderSecurityKeywordManagementService;
    @Resource
    private ISysAttachmentService sysAttachmentService;
    @Resource
    private ITenderProjectNoticeService tenderProjectNoticeService;

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        List<SendProjectNoticeReqDto> noticeInfoList = new ArrayList<>();
        WebDriver driver = null;
        try {
            driver = webDriverConfig.driver(JOB_NAME);
            Map<Long, String> lableMap = tenderSecurityKeywordManagementService.getCacheSecurityKeywordManagement();
            // 招标工作筛选条件; 00-未开始报名, 01-报名中
            List<String> statusList = Arrays.asList("00", "01");
            for (String status: statusList) {
                int pageIdx = 1, totalPage = -1;
                do {
                    // 获取当前最大页
                    int day = 3;
                    String searchDate = DateUtils.formatDate(DateUtils.calculate(new Date(), -day, Calendar.DAY_OF_MONTH), DateUtils.DATE_PATTERN);
                    String url = String.format("https://cg.11185.cn/zgyzcms/category/bulletinList.html?searchDate=%s&dates=%d&goSearch=&categoryId=88&tabName=采购信息&industryName=&status=%s&signDate=%s,lt&page=%d",
                            searchDate, day, status, DateUtils.formatDateTime(new Date()), pageIdx++);
                    driver.get(url);
                    driver.navigate().refresh();
                    // 获取最大页
                    if (totalPage <= 0) {
                        WebElement elements = driver.findElement(By.cssSelector(".pages label"));
                        totalPage = Integer.parseInt(elements.getText());
                    }
                    log.info("开始抓取邮政采购网信息: {}, 共需要扫描{}页的信息", url, totalPage);
                    // 获取表格中的采购标题和信息
                    List<WebElement> lis = new WebDriverWait(driver, Duration.ofSeconds(20))
                            .until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.cssSelector("ul.newslist > li")));
                    for (WebElement li: lis) {
                        String href = li.findElement(By.cssSelector("a")).getAttribute("href");
                        String title = li.findElement(By.cssSelector("a")).getAttribute("title");

                        // 检查时间范围
                        long count = tenderInformationService.lambdaQuery().eq(TenderInformation::getTenderTitle, title).count();
                        if (count > 0) {
                            log.info("{}已经抓取", title);
                            continue;
                        }
                        List<Long> lableList = lableMap.entrySet().stream()
                                .filter(entry -> title.contains(entry.getValue())).map(Map.Entry::getKey)
                                .collect(Collectors.toList());
                        if (ObjectUtils.isEmpty(lableList)) {
                            log.debug("{}没有安全标签", title);
                            continue;
                        }

                        String projectCode = li.findElement(By.cssSelector("ul.newsinfo > li:nth-of-type(1) span")).getText();
                        String type = li.findElement(By.cssSelector("ul.newsinfo > li:nth-of-type(2) span")).getText();
                        String endDate = li.findElement(By.cssSelector("ul.newsinfo > li:nth-of-type(3) span")).getText();
                        String pubDate = li.findElement(By.cssSelector("div.newsDate")).getText().replace("\n", "/");
                        // 打开新标签页去获取招标的明细信息
                        driver.switchTo().newWindow(WindowType.TAB).get(href);

                        try {
                            downloadRetryDetail(0, title, driver);
                            // 检查文件是否下载完成
                            File pdfFile = webDriverConfig.waitForDownloadToComplete(JOB_NAME, 20);
                            Result<Long> result = sysAttachmentService.uploadFile(pdfFile, "system", MessageSNUtil.generateFileMessageSN());
                            FileUtil.delete(pdfFile);

                            TenderInformation information = BuildTenderInfo.buildTenderInfo(title, projectCode, type, pubDate, endDate, result.getResult());
                            tenderInformationService.saveCg11185(lableList, information, noticeInfoList,href);
                            // 切回主页面
                            driver.close();
                            driver.switchTo().window(new ArrayList<>(driver.getWindowHandles()).get(0));
                        } catch (Exception e) {
                            log.warn("抓取失败", e);
                            List<String> pageHandlers = new ArrayList<>(driver.getWindowHandles());
                            if (pageHandlers.size() > 1) {
                                // 最多开启两个标签页，关闭其中一个
                                driver.close();
                            }
                            driver.switchTo().window(pageHandlers.get(0));
                        }
                    }
                } while (pageIdx <= totalPage);
            }
        } catch (Exception e) {
            log.warn("爬取邮政采购网失败;", e);
        } finally {
            // 发送通知
            tenderProjectNoticeService.sendTenderProjectNotice(noticeInfoList);
            if (null != driver) {
                driver.quit();
            }
            log.info("邮政采购网爬取任务结束");
        }
    }

    private void downloadRetryDetail(int retry, String title, WebDriver driver) {
        try {
            WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20));
            WebElement pdfElement = wait.until(ExpectedConditions.presenceOfElementLocated(By.id("pdfContainer")));
            driver.switchTo().frame(pdfElement);

            // 等待pdf渲染完成
            new WebDriverWait(driver, Duration.ofSeconds(10))
                    .until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#viewerContainer > #viewer > .page")));

            // 下载文件
            driver.findElement(By.cssSelector("#download")).click();

            // 切换回原来页
            driver.switchTo().defaultContent();
        } catch (Exception e) {
            // 失败情况下重新刷新页面再试
            driver.navigate().refresh();
            // 重试三次
            if (retry >= 3) {
                log.warn("超出最大重试次数页面抓取[{}]失败", title);
                return;
            }
            downloadRetryDetail(retry + 1, title, driver);
        }
    }


}
